/**
 * @file    elog.c
 * @brief   EasyLogger核心实现文件
 * @details 本文件实现了EasyLogger日志库的核心功能，包括：
 *          - 日志输出的核心处理逻辑
 *          - 日志格式化和级别控制
 *          - 过滤器功能实现（标签、关键字、级别过滤）
 *          - 初始化和启动控制
 *          - 与异步输出和缓冲输出的集成
 */

#define LOG_TAG      "elog"                                                 /* 当前模块的日志标签 */

#include <elog.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>

#if !defined(ELOG_OUTPUT_LVL)
    #error "Please configure static output log level (in elog_cfg.h)"
#endif

#if !defined(ELOG_LINE_NUM_MAX_LEN)
    #error "Please configure output line number max length (in elog_cfg.h)"
#endif

#if !defined(ELOG_LINE_BUF_SIZE)
    #error "Please configure buffer size for every line's log (in elog_cfg.h)"
#endif

#if !defined(ELOG_FILTER_TAG_MAX_LEN)
    #error "Please configure output filter's tag max length (in elog_cfg.h)"
#endif

#if !defined(ELOG_FILTER_KW_MAX_LEN)
    #error "Please configure output filter's keyword max length (in elog_cfg.h)"
#endif

#if !defined(ELOG_NEWLINE_SIGN)
    #error "Please configure output newline sign (in elog_cfg.h)"
#endif

/* 输出过滤器标签级别最大数量 */
#ifndef ELOG_FILTER_TAG_LVL_MAX_NUM
#define ELOG_FILTER_TAG_LVL_MAX_NUM          4                              /* 默认标签级别过滤器数量 */
#endif

#ifdef ELOG_COLOR_ENABLE
/* ---------------------------------------------- ANSI颜色控制定义 ------------------------------------------ */
/**
 * CSI(Control Sequence Introducer/Initiator) 控制序列标识符
 * 更多信息请参考: https://en.wikipedia.org/wiki/ANSI_escape_code
 */
#define CSI_START                      "\033["                              /* ANSI转义序列开始标志 */
#define CSI_END                        "\033[0m"                            /* ANSI转义序列结束标志 */
/* 日志前景色定义 */
#define F_BLACK                        "30;"                                /* 黑色前景 */
#define F_RED                          "31;"                                /* 红色前景 */
#define F_GREEN                        "32;"                                /* 绿色前景 */
#define F_YELLOW                       "33;"                                /* 黄色前景 */
#define F_BLUE                         "34;"                                /* 蓝色前景 */
#define F_MAGENTA                      "35;"                                /* 洋红色前景 */
#define F_CYAN                         "36;"                                /* 青色前景 */
#define F_WHITE                        "37;"                                /* 白色前景 */
/* 日志背景色定义 */
#define B_NULL                                                              /* 无背景色 */
#define B_BLACK                        "40;"                                /* 黑色背景 */
#define B_RED                          "41;"                                /* 红色背景 */
#define B_GREEN                        "42;"                                /* 绿色背景 */
#define B_YELLOW                       "43;"                                /* 黄色背景 */
#define B_BLUE                         "44;"                                /* 蓝色背景 */
#define B_MAGENTA                      "45;"                                /* 洋红色背景 */
#define B_CYAN                         "46;"                                /* 青色背景 */
#define B_WHITE                        "47;"                                /* 白色背景 */
/* 日志字体样式定义 */
#define S_BOLD                         "1m"                                 /* 粗体样式 */
#define S_UNDERLINE                    "4m"                                 /* 下划线样式 */
#define S_BLINK                        "5m"                                 /* 闪烁样式 */
#define S_NORMAL                       "22m"                                /* 正常样式 */
/* 日志默认颜色定义: [前景色] + [背景色] + [显示样式] */
#ifndef ELOG_COLOR_ASSERT
#define ELOG_COLOR_ASSERT              (F_MAGENTA B_NULL S_NORMAL)          /* 断言级别颜色 */
#endif
#ifndef ELOG_COLOR_ERROR
#define ELOG_COLOR_ERROR               (F_RED B_NULL S_NORMAL)              /* 错误级别颜色 */
#endif
#ifndef ELOG_COLOR_WARN
#define ELOG_COLOR_WARN                (F_YELLOW B_NULL S_NORMAL)           /* 警告级别颜色 */
#endif
#ifndef ELOG_COLOR_INFO
#define ELOG_COLOR_INFO                (F_CYAN B_NULL S_NORMAL)             /* 信息级别颜色 */
#endif
#ifndef ELOG_COLOR_DEBUG
#define ELOG_COLOR_DEBUG               (F_GREEN B_NULL S_NORMAL)            /* 调试级别颜色 */
#endif
#ifndef ELOG_COLOR_VERBOSE
#define ELOG_COLOR_VERBOSE             (F_BLUE B_NULL S_NORMAL)             /* 详细级别颜色 */
#endif
#endif /* ELOG_COLOR_ENABLE */

/* ---------------------------------------------- 全局变量定义 ---------------------------------------------- */
static EasyLogger elog;                                                     /* EasyLogger主对象 */
static char log_buf[ELOG_LINE_BUF_SIZE] = { 0 };                            /* 每行日志的缓冲区 */
/* 日志级别输出信息数组 */
static const char *level_output_info[] = {
        [ELOG_LVL_ASSERT]  = "A/",                                          /* 断言级别标识 */
        [ELOG_LVL_ERROR]   = "E/",                                          /* 错误级别标识 */
        [ELOG_LVL_WARN]    = "W/",                                          /* 警告级别标识 */
        [ELOG_LVL_INFO]    = "I/",                                          /* 信息级别标识 */
        [ELOG_LVL_DEBUG]   = "D/",                                          /* 调试级别标识 */
        [ELOG_LVL_VERBOSE] = "V/",                                          /* 详细级别标识 */
};

#ifdef ELOG_COLOR_ENABLE
/* 颜色输出信息数组 */
static const char *color_output_info[] = {
        [ELOG_LVL_ASSERT]  = ELOG_COLOR_ASSERT,                             /* 断言级别颜色 */
        [ELOG_LVL_ERROR]   = ELOG_COLOR_ERROR,                              /* 错误级别颜色 */
        [ELOG_LVL_WARN]    = ELOG_COLOR_WARN,                               /* 警告级别颜色 */
        [ELOG_LVL_INFO]    = ELOG_COLOR_INFO,                               /* 信息级别颜色 */
        [ELOG_LVL_DEBUG]   = ELOG_COLOR_DEBUG,                              /* 调试级别颜色 */
        [ELOG_LVL_VERBOSE] = ELOG_COLOR_VERBOSE,                            /* 详细级别颜色 */
};
#endif /* ELOG_COLOR_ENABLE */

/* ---------------------------------------------- 静态函数声明 ---------------------------------------------- */
static bool get_fmt_enabled(uint8_t level, size_t set);                     /* 获取格式化选项是否启用 */
static bool get_fmt_used_and_enabled_u32(uint8_t level, size_t set, uint32_t arg);      /* 检查32位参数格式化选项 */
static bool get_fmt_used_and_enabled_ptr(uint8_t level, size_t set, const char* arg);   /* 检查指针参数格式化选项 */
static void elog_set_filter_tag_lvl_default(void);                          /* 设置标签级别过滤器默认值 */

/* ---------------------------------------------- 钩子函数指针 ---------------------------------------------- */
void (*elog_assert_hook)(const char* expr, const char* func, size_t line);  /* EasyLogger断言钩子函数 */

/* ---------------------------------------------- 外部函数声明 ---------------------------------------------- */
extern void elog_port_output(const char *log, size_t size);                 /* 移植层输出函数 */
extern void elog_port_output_lock(void);                                    /* 移植层输出锁定函数 */
extern void elog_port_output_unlock(void);                                  /* 移植层输出解锁函数 */

/* ---------------------------------------------- 初始化和控制函数 -------------------------------------------- */
/**
 * @brief  EasyLogger初始化函数
 * @return 初始化结果
 * @retval ELOG_NO_ERR 初始化成功
 * @note   此函数必须在使用EasyLogger之前调用
 */
ElogErrCode elog_init(void)
{
    extern ElogErrCode elog_port_init(void);                                /* 移植层初始化函数 */
    extern ElogErrCode elog_async_init(void);                               /* 异步输出初始化函数 */

    ElogErrCode result = ELOG_NO_ERR;                                       /* 初始化结果 */

    if (elog.init_ok == true)
    {
        return result;                                                      /* 已初始化，直接返回 */
    }

    /* 移植层初始化 */
    result = elog_port_init();
    if (result != ELOG_NO_ERR)
    {
        return result;                                                      /* 移植层初始化失败 */
    }

#ifdef ELOG_ASYNC_OUTPUT_ENABLE
    result = elog_async_init();                                             /* 异步输出初始化 */
    if (result != ELOG_NO_ERR)
    {
        return result;                                                      /* 异步输出初始化失败 */
    }
#endif

    /* 启用输出锁 */
    elog_output_lock_enabled(true);
    /* 初始化输出锁定状态 */
    elog.output_is_locked_before_enable = false;
    elog.output_is_locked_before_disable = false;

#ifdef ELOG_COLOR_ENABLE
    /* 默认启用文本颜色 */
    elog_set_text_color_enabled(true);
#endif

    /* 设置日志级别为详细级别 */
    elog_set_filter_lvl(ELOG_LVL_VERBOSE);

    /* 设置标签级别过滤器为默认值 */
    elog_set_filter_tag_lvl_default();

    elog.init_ok = true;                                                    /* 标记初始化完成 */

    return result;
}

/**
 * @brief  EasyLogger反初始化函数
 * @note   此函数用于清理EasyLogger资源
 */
void elog_deinit(void)
{
    extern ElogErrCode elog_port_deinit(void);                              /* 移植层反初始化函数 */
    extern ElogErrCode elog_async_deinit(void);                             /* 异步输出反初始化函数 */

    if (!elog.init_ok)
    {
        return;                                                             /* 未初始化，直接返回 */
    }
    
#ifdef ELOG_ASYNC_OUTPUT_ENABLE
    elog_async_deinit();                                                    /* 异步输出反初始化 */
#endif

    /* 移植层反初始化 */
    elog_port_deinit();

    elog.init_ok = false;                                                   /* 标记反初始化完成 */
}


/**
 * @brief  EasyLogger启动函数
 * @note   在初始化后调用此函数开始日志输出
 */
void elog_start(void)
{
    if (!elog.init_ok)
    {
        return;                                                             /* 未初始化，直接返回 */
    }
    
    /* 启用日志输出 */
    elog_set_output_enabled(true);

#if defined(ELOG_ASYNC_OUTPUT_ENABLE)
    elog_async_enabled(true);                                               /* 启用异步输出模式 */
#elif defined(ELOG_BUF_OUTPUT_ENABLE)
    elog_buf_enabled(true);                                                 /* 启用缓冲输出模式 */
#endif

    /* 显示版本信息 */
    log_i("EasyLogger V%s is initialize success.", ELOG_SW_VERSION);
}

/**
 * @brief  EasyLogger停止函数
 * @note   在初始化后调用此函数停止日志输出
 */
void elog_stop(void)
{
    if (!elog.init_ok)
    {
        return;                                                             /* 未初始化，直接返回 */
    }

    /* 禁用日志输出 */
    elog_set_output_enabled(false);

#if defined(ELOG_ASYNC_OUTPUT_ENABLE)
    elog_async_enabled(false);                                              /* 禁用异步输出模式 */
#elif defined(ELOG_BUF_OUTPUT_ENABLE)
    elog_buf_enabled(false);                                                /* 禁用缓冲输出模式 */
#endif

    /* 显示版本信息 */
    log_i("EasyLogger V%s is deinitialize success.", ELOG_SW_VERSION);
}


/* ---------------------------------------------- 输出控制函数 ---------------------------------------------- */
/**
 * @brief  设置日志输出启用或禁用
 * @param  enabled true: 启用, false: 禁用
 */
void elog_set_output_enabled(bool enabled)
{
    ELOG_ASSERT((enabled == false) || (enabled == true));                   /* 断言参数有效性 */

    elog.output_enabled = enabled;                                          /* 设置输出启用状态 */
}

#ifdef ELOG_COLOR_ENABLE
/**
 * @brief  设置日志文本颜色启用或禁用
 * @param  enabled true: 启用, false: 禁用
 */
void elog_set_text_color_enabled(bool enabled)
{
    ELOG_ASSERT((enabled == false) || (enabled == true));                   /* 断言参数有效性 */

    elog.text_color_enabled = enabled;                                      /* 设置文本颜色启用状态 */
}

/**
 * @brief  获取日志文本颜色启用状态
 * @return 颜色启用状态
 * @retval true 已启用
 * @retval false 已禁用
 */
bool elog_get_text_color_enabled(void)
{
    return elog.text_color_enabled;                                         /* 返回文本颜色启用状态 */
}
#endif /* ELOG_COLOR_ENABLE */

/**
 * @brief  获取日志输出启用状态
 * @return 输出启用状态
 * @retval true 已启用
 * @retval false 已禁用
 */
bool elog_get_output_enabled(void)
{
    return elog.output_enabled;                                             /* 返回输出启用状态 */
}

/* ---------------------------------------------- 格式化设置函数 ---------------------------------------------- */
/**
 * @brief  设置日志输出格式
 * @param  level 日志级别
 * @param  set 格式化选项集合
 * @note   只能启用或禁用格式化选项
 */
void elog_set_fmt(uint8_t level, size_t set)
{
    ELOG_ASSERT(level <= ELOG_LVL_VERBOSE);                                 /* 断言级别有效性 */

    elog.enabled_fmt_set[level] = set;                                      /* 设置指定级别的格式化选项 */
}

/* ---------------------------------------------- 过滤器设置函数 ---------------------------------------------- */
/**
 * @brief  设置日志过滤器所有参数
 * @param  level 日志级别
 * @param  tag 标签名称
 * @param  keyword 关键字
 * @note   此函数一次性设置所有过滤器参数
 */
void elog_set_filter(uint8_t level, const char *tag, const char *keyword)
{
    ELOG_ASSERT(level <= ELOG_LVL_VERBOSE);                                 /* 断言级别有效性 */

    elog_set_filter_lvl(level);                                             /* 设置过滤器级别 */
    elog_set_filter_tag(tag);                                               /* 设置过滤器标签 */
    elog_set_filter_kw(keyword);                                            /* 设置过滤器关键字 */
}

/**
 * @brief  设置日志过滤器的级别
 * @param  level 日志级别
 * @note   只有级别大于或等于此级别的日志才会输出
 */
void elog_set_filter_lvl(uint8_t level)
{
    ELOG_ASSERT(level <= ELOG_LVL_VERBOSE);                                 /* 断言级别有效性 */

    elog.filter.level = level;                                              /* 设置过滤器级别 */
}

/**
 * @brief  设置日志过滤器的标签
 * @param  tag 标签名称
 * @note   只有包含此标签的日志才会输出
 */
void elog_set_filter_tag(const char *tag)
{
    strncpy(elog.filter.tag, tag, ELOG_FILTER_TAG_MAX_LEN);                 /* 复制标签到过滤器 */
}

/**
 * @brief  设置日志过滤器的关键字
 * @param  keyword 关键字
 * @note   只有包含此关键字的日志才会输出
 */
void elog_set_filter_kw(const char *keyword)
{
    strncpy(elog.filter.keyword, keyword, ELOG_FILTER_KW_MAX_LEN);          /* 复制关键字到过滤器 */
}

/* ---------------------------------------------- 输出锁控制函数 ---------------------------------------------- */
/**
 * @brief  锁定日志输出
 * @note   用于多线程环境下保证输出的原子性
 */
void elog_output_lock(void)
{
    if (elog.output_lock_enabled)
    {
        elog_port_output_lock();                                            /* 调用移植层锁定函数 */
        elog.output_is_locked_before_disable = true;                        /* 记录锁定状态 */
    }
    else
    {
        elog.output_is_locked_before_enable = true;                         /* 记录锁定状态 */
    }
}

/**
 * @brief  解锁日志输出
 * @note   用于多线程环境下保证输出的原子性
 */
void elog_output_unlock(void)
{
    if (elog.output_lock_enabled)
    {
        elog_port_output_unlock();                                          /* 调用移植层解锁函数 */
        elog.output_is_locked_before_disable = false;                       /* 记录解锁状态 */
    }
    else
    {
        elog.output_is_locked_before_enable = false;                        /* 记录解锁状态 */
    }
}

/**
 * @brief  设置标签级别过滤器为默认值
 * @note   内部函数，用于初始化标签级别过滤器数组
 */
static void elog_set_filter_tag_lvl_default(void)
{
    uint8_t i = 0;

    for (i = 0; i < ELOG_FILTER_TAG_LVL_MAX_NUM; i++)                       /* 遍历所有标签级别过滤器 */
    {
        memset(elog.filter.tag_lvl[i].tag, '\0', ELOG_FILTER_TAG_MAX_LEN + 1);  /* 清空标签字符串 */
        elog.filter.tag_lvl[i].level = ELOG_FILTER_LVL_SILENT;              /* 设置为静默级别 */
        elog.filter.tag_lvl[i].tag_use_flag = false;                        /* 标记为未使用 */
    }
}

/**
 * @brief  按标签设置过滤器级别
 * @param  tag 日志标签
 * @param  level 过滤器级别
 * @note   低于此级别的日志将停止输出
 *         当级别为ELOG_FILTER_LVL_SILENT时，该标签进入静默模式
 *         当级别为ELOG_FILTER_LVL_ALL时，移除该标签的级别过滤器
 * @example
 *         elog_set_filter_tag_lvl("example", ELOG_FILTER_LVL_SILENT);  // 静默模式
 *         elog_set_filter_tag_lvl("example", ELOG_LVL_INFO);           // 只输出INFO及以上级别
 *         elog_set_filter_tag_lvl("example", ELOG_FILTER_LVL_ALL);     // 移除过滤器
 */
void elog_set_filter_tag_lvl(const char *tag, uint8_t level)
{
    ELOG_ASSERT(level <= ELOG_LVL_VERBOSE);                                 /* 断言级别有效性 */
    ELOG_ASSERT(tag != ((void *)0));                                        /* 断言标签非空 */
    uint8_t i = 0;

    if (!elog.init_ok)                                                      /* 检查初始化状态 */
    {
        return;
    }

    elog_output_lock();                                                     /* 锁定输出 */
    
    /* 在数组中查找标签 */
    for (i = 0; i < ELOG_FILTER_TAG_LVL_MAX_NUM; i++)
    {
        if (elog.filter.tag_lvl[i].tag_use_flag == true &&
            !strncmp(tag, elog.filter.tag_lvl[i].tag, ELOG_FILTER_TAG_MAX_LEN))
        {
            break;                                                          /* 找到匹配的标签 */
        }
    }

    if (i < ELOG_FILTER_TAG_LVL_MAX_NUM)                                    /* 找到标签 */
    {
        if (level == ELOG_FILTER_LVL_ALL)                                   /* 移除过滤器 */
        {
            elog.filter.tag_lvl[i].tag_use_flag = false;                    /* 标记为未使用 */
            memset(elog.filter.tag_lvl[i].tag, '\0', ELOG_FILTER_TAG_MAX_LEN + 1);  /* 清空标签 */
            elog.filter.tag_lvl[i].level = ELOG_FILTER_LVL_SILENT;          /* 重置级别 */
        }
        else
        {
            elog.filter.tag_lvl[i].level = level;                           /* 设置新级别 */
        }
    }
    else                                                                    /* 未找到标签 */
    {
        /* 只有当级别不是ELOG_FILTER_LVL_ALL时才添加新的标签过滤器 */
        if (level != ELOG_FILTER_LVL_ALL)
        {
            for (i = 0; i < ELOG_FILTER_TAG_LVL_MAX_NUM; i++)               /* 查找空闲位置 */
            {
                if (elog.filter.tag_lvl[i].tag_use_flag == false)
                {
                    strncpy(elog.filter.tag_lvl[i].tag, tag, ELOG_FILTER_TAG_MAX_LEN);  /* 复制标签 */
                    elog.filter.tag_lvl[i].level = level;                   /* 设置级别 */
                    elog.filter.tag_lvl[i].tag_use_flag = true;             /* 标记为使用 */
                    break;
                }
            }
        }
    }
    elog_output_unlock();                                                   /* 解锁输出 */
}

/**
 * @brief  获取标签的过滤器级别
 * @param  tag 日志标签
 * @return 标签的过滤器级别，未找到时返回最低级别
 * @note   用于检查指定标签的过滤器设置
 */
uint8_t elog_get_filter_tag_lvl(const char *tag)
{
    ELOG_ASSERT(tag != ((void *)0));                                        /* 断言标签非空 */
    uint8_t i = 0;
    uint8_t level = ELOG_FILTER_LVL_ALL;                                    /* 默认为最低级别 */

    if (!elog.init_ok)                                                      /* 检查初始化状态 */
    {
        return level;
    }

    elog_output_lock();                                                     /* 锁定输出 */
    
    /* 在数组中查找标签 */
    for (i = 0; i < ELOG_FILTER_TAG_LVL_MAX_NUM; i++)
    {
        if (elog.filter.tag_lvl[i].tag_use_flag == true &&
            !strncmp(tag, elog.filter.tag_lvl[i].tag, ELOG_FILTER_TAG_MAX_LEN))
        {
            level = elog.filter.tag_lvl[i].level;                           /* 获取标签级别 */
            break;
        }
    }
    elog_output_unlock();                                                   /* 解锁输出 */

    return level;                                                           /* 返回级别 */
}

/* ---------------------------------------------- 日志输出函数 ---------------------------------------------- */
/**
 * @brief  输出原始格式日志
 * @param  format 输出格式字符串
 * @param  ... 可变参数
 * @note   直接输出，不经过级别和标签过滤
 */
void elog_raw_output(const char *format, ...)
{
    va_list args;
    size_t log_len = 0;
    int fmt_result;

    /* 检查输出是否启用 */
    if (!elog.output_enabled)
    {
        return;
    }

    /* 参数指向第一个可变参数 */
    va_start(args, format);

    /* 锁定输出 */
    elog_output_lock();

    /* 将日志数据格式化到缓冲区 */
    fmt_result = vsnprintf(log_buf, ELOG_LINE_BUF_SIZE, format, args);

    /* 计算输出长度 */
    if ((fmt_result > -1) && (fmt_result <= ELOG_LINE_BUF_SIZE))
    {
        log_len = fmt_result;                                               /* 使用实际长度 */
    }
    else
    {
        log_len = ELOG_LINE_BUF_SIZE;                                       /* 使用最大长度 */
    }
    
    /* 输出日志 */
#if defined(ELOG_ASYNC_OUTPUT_ENABLE)
    extern void elog_async_output(uint8_t level, const char *log, size_t size);
    /* 原始日志使用断言级别 */
    elog_async_output(ELOG_LVL_ASSERT, log_buf, log_len);
#elif defined(ELOG_BUF_OUTPUT_ENABLE)
    extern void elog_buf_output(const char *log, size_t size);
    elog_buf_output(log_buf, log_len);                                      /* 缓冲输出 */
#else
    elog_port_output(log_buf, log_len);                                     /* 直接输出 */
#endif
    
    /* 解锁输出 */
    elog_output_unlock();

    va_end(args);                                                           /* 结束可变参数处理 */
}

/**
 * @brief  输出格式化日志
 * @param  level 日志级别
 * @param  tag 日志标签
 * @param  file 文件名
 * @param  func 函数名
 * @param  line 行号
 * @param  format 格式化字符串
 * @param  ... 可变参数
 * @note   核心日志输出函数，支持级别过滤、标签过滤、关键字过滤
 */
void elog_output(uint8_t level, const char *tag, const char *file, const char *func,
        const long line, const char *format, ...)
{
    extern const char *elog_port_get_time(void);                            /* 获取时间信息 */
    extern const char *elog_port_get_p_info(void);                          /* 获取进程信息 */
    extern const char *elog_port_get_t_info(void);                          /* 获取线程信息 */

    size_t tag_len = strlen(tag), log_len = 0, newline_len = strlen(ELOG_NEWLINE_SIGN);
    char line_num[ELOG_LINE_NUM_MAX_LEN + 1] = { 0 };                       /* 行号字符串缓冲区 */
    char tag_sapce[ELOG_FILTER_TAG_MAX_LEN / 2 + 1] = { 0 };                /* 标签空格填充缓冲区 */
    va_list args;
    int fmt_result;

    ELOG_ASSERT(level <= ELOG_LVL_VERBOSE);                                 /* 断言级别有效性 */

    /* 检查输出是否启用 */
    if (!elog.output_enabled)
    {
        return;
    }
    
    /* 级别过滤 */
    if (level > elog.filter.level || level > elog_get_filter_tag_lvl(tag))
    {
        return;
    }
    else if (!strstr(tag, elog.filter.tag))                                 /* 标签过滤 */
    {
        return;
    }
    
    /* 参数指向第一个可变参数 */
    va_start(args, format);
    
    /* 锁定输出 */
    elog_output_lock();

#ifdef ELOG_COLOR_ENABLE
    /* 添加颜色控制序列起始标志 */
    if (elog.text_color_enabled)
    {
        log_len += elog_strcpy(log_len, log_buf + log_len, CSI_START);      /* 添加CSI起始标志 */
        log_len += elog_strcpy(log_len, log_buf + log_len, color_output_info[level]);   /* 添加颜色信息 */
    }
#endif

    /* 封装级别信息 */
    if (get_fmt_enabled(level, ELOG_FMT_LVL))
    {
        log_len += elog_strcpy(log_len, log_buf + log_len, level_output_info[level]);   /* 添加级别字符串 */
    }
    
    /* 封装标签信息 */
    if (get_fmt_enabled(level, ELOG_FMT_TAG))
    {
        log_len += elog_strcpy(log_len, log_buf + log_len, tag);            /* 添加标签 */
        
        /* 如果标签长度小于最大长度的50%，则填充空格对齐 */
        if (tag_len <= ELOG_FILTER_TAG_MAX_LEN / 2)
        {
            memset(tag_sapce, ' ', ELOG_FILTER_TAG_MAX_LEN / 2 - tag_len);  /* 生成空格填充 */
            log_len += elog_strcpy(log_len, log_buf + log_len, tag_sapce);  /* 添加空格填充 */
        }
        log_len += elog_strcpy(log_len, log_buf + log_len, " ");            /* 添加分隔空格 */
    }
    /* 封装时间、进程和线程信息 */
    if (get_fmt_enabled(level, ELOG_FMT_TIME | ELOG_FMT_P_INFO | ELOG_FMT_T_INFO))
    {
        log_len += elog_strcpy(log_len, log_buf + log_len, "[");            /* 添加左括号 */
        
        /* 封装时间信息 */
        if (get_fmt_enabled(level, ELOG_FMT_TIME))
        {
            log_len += elog_strcpy(log_len, log_buf + log_len, elog_port_get_time());   /* 添加时间戳 */
            if (get_fmt_enabled(level, ELOG_FMT_P_INFO | ELOG_FMT_T_INFO))
            {
                log_len += elog_strcpy(log_len, log_buf + log_len, " ");    /* 添加分隔空格 */
            }
        }
        
        /* 封装进程信息 */
        if (get_fmt_enabled(level, ELOG_FMT_P_INFO))
        {
            log_len += elog_strcpy(log_len, log_buf + log_len, elog_port_get_p_info()); /* 添加进程信息 */
            if (get_fmt_enabled(level, ELOG_FMT_T_INFO))
            {
                log_len += elog_strcpy(log_len, log_buf + log_len, " ");    /* 添加分隔空格 */
            }
        }
        
        /* 封装线程信息 */
        if (get_fmt_enabled(level, ELOG_FMT_T_INFO))
        {
            log_len += elog_strcpy(log_len, log_buf + log_len, elog_port_get_t_info()); /* 添加线程信息 */
        }
        log_len += elog_strcpy(log_len, log_buf + log_len, "] ");           /* 添加右括号和空格 */
    }
    /* 封装文件目录、函数名和行号信息 */
    if (get_fmt_used_and_enabled_ptr(level, ELOG_FMT_DIR, file) ||
            get_fmt_used_and_enabled_ptr(level, ELOG_FMT_FUNC, func) ||
            get_fmt_used_and_enabled_u32(level, ELOG_FMT_LINE, line))
    {
        log_len += elog_strcpy(log_len, log_buf + log_len, "(");            /* 添加左括号 */
        
        /* 封装文件信息 */
        if (get_fmt_used_and_enabled_ptr(level, ELOG_FMT_DIR, file))
        {
            log_len += elog_strcpy(log_len, log_buf + log_len, file);       /* 添加文件名 */
            if (get_fmt_used_and_enabled_ptr(level, ELOG_FMT_FUNC, func))
            {
                log_len += elog_strcpy(log_len, log_buf + log_len, ":");    /* 添加冒号分隔符 */
            }
            else if (get_fmt_used_and_enabled_u32(level, ELOG_FMT_LINE, line))
            {
                log_len += elog_strcpy(log_len, log_buf + log_len, " ");    /* 添加空格分隔符 */
            }
        }
        
        /* 封装行号信息 */
        if (get_fmt_used_and_enabled_u32(level, ELOG_FMT_LINE, line))
        {
            snprintf(line_num, ELOG_LINE_NUM_MAX_LEN, "%ld", line);         /* 格式化行号 */
            log_len += elog_strcpy(log_len, log_buf + log_len, line_num);   /* 添加行号 */
            if (get_fmt_used_and_enabled_ptr(level, ELOG_FMT_FUNC, func))
            {
                log_len += elog_strcpy(log_len, log_buf + log_len, " ");    /* 添加空格分隔符 */
            }
        }
        
        /* 封装函数信息 */
        if (get_fmt_used_and_enabled_ptr(level, ELOG_FMT_FUNC, func))
        {
            log_len += elog_strcpy(log_len, log_buf + log_len, func);       /* 添加函数名 */
        }
        log_len += elog_strcpy(log_len, log_buf + log_len, ")");            /* 添加右括号 */
    }
    /* 将其他日志数据格式化到缓冲区，vsnprintf会在末尾自动添加'\0' */
    fmt_result = vsnprintf(log_buf + log_len, ELOG_LINE_BUF_SIZE - log_len, format, args);

    va_end(args);                                                           /* 结束可变参数处理 */
    
    /* 计算日志长度 */
    if ((log_len + fmt_result <= ELOG_LINE_BUF_SIZE) && (fmt_result > -1))
    {
        log_len += fmt_result;                                              /* 使用实际长度 */
    }
    else
    {
        log_len = ELOG_LINE_BUF_SIZE;                                       /* 使用最大长度 */
    }
    
    /* 溢出检查并为CSI结束标志和换行符预留空间 */
#ifdef ELOG_COLOR_ENABLE
    if (log_len + (sizeof(CSI_END) - 1) + newline_len > ELOG_LINE_BUF_SIZE)
    {
        log_len = ELOG_LINE_BUF_SIZE;                                       /* 使用最大长度 */
        log_len -= (sizeof(CSI_END) - 1);                                   /* 为CSI结束标志预留空间 */
#else
    if (log_len + newline_len > ELOG_LINE_BUF_SIZE)
    {
        log_len = ELOG_LINE_BUF_SIZE;                                       /* 使用最大长度 */
#endif /* ELOG_COLOR_ENABLE */
        log_len -= newline_len;                                             /* 为换行符预留空间 */
    }
    
    /* 关键字过滤 */
    if (elog.filter.keyword[0] != '\0')
    {
        log_buf[log_len] = '\0';                                            /* 添加字符串结束标志 */
        
        /* 查找关键字 */
        if (!strstr(log_buf, elog.filter.keyword))
        {
            elog_output_unlock();                                           /* 解锁输出 */
            return;                                                         /* 不包含关键字，直接返回 */
        }
    }

#ifdef ELOG_COLOR_ENABLE
    /* 添加颜色控制序列结束标志 */
    if (elog.text_color_enabled)
    {
        log_len += elog_strcpy(log_len, log_buf + log_len, CSI_END);        /* 添加CSI结束标志 */
    }
#endif

    /* 封装换行符 */
    log_len += elog_strcpy(log_len, log_buf + log_len, ELOG_NEWLINE_SIGN);  /* 添加换行符 */
    
    /* 输出日志 */
#if defined(ELOG_ASYNC_OUTPUT_ENABLE)
    extern void elog_async_output(uint8_t level, const char *log, size_t size);
    elog_async_output(level, log_buf, log_len);                             /* 异步输出 */
#elif defined(ELOG_BUF_OUTPUT_ENABLE)
    extern void elog_buf_output(const char *log, size_t size);
    elog_buf_output(log_buf, log_len);                                      /* 缓冲输出 */
#else
    elog_port_output(log_buf, log_len);                                     /* 直接输出 */
#endif
    
    /* 解锁输出 */
    elog_output_unlock();
}

/* ---------------------------------------------- 格式化辅助函数 ---------------------------------------------- */
/**
 * @brief  获取格式化选项是否启用
 * @param  level 日志级别
 * @param  set 格式化选项集合
 * @return 启用状态
 * @note   内部函数，用于检查指定级别的格式化选项是否启用
 */
static bool get_fmt_enabled(uint8_t level, size_t set)
{
    ELOG_ASSERT(level <= ELOG_LVL_VERBOSE);                                 /* 断言级别有效性 */

    if (elog.enabled_fmt_set[level] & set)                                  /* 检查格式化选项 */
    {
        return true;                                                        /* 已启用 */
    }
    else
    {
        return false;                                                       /* 未启用 */
    }
}

/**
 * @brief  检查32位参数是否有效且格式化选项已启用
 * @param  level 日志级别
 * @param  set 格式化选项集合
 * @param  arg 32位参数值
 * @return 参数有效且选项启用时返回true
 * @note   内部函数，用于检查参数有效性和格式化选项状态
 */
static bool get_fmt_used_and_enabled_u32(uint8_t level, size_t set, uint32_t arg)
{
    return arg && get_fmt_enabled(level, set);                              /* 参数有效且选项启用 */
}

/**
 * @brief  检查指针参数是否有效且格式化选项已启用
 * @param  level 日志级别
 * @param  set 格式化选项集合
 * @param  arg 指针参数
 * @return 参数有效且选项启用时返回true
 * @note   内部函数，用于检查参数有效性和格式化选项状态
 */
static bool get_fmt_used_and_enabled_ptr(uint8_t level, size_t set, const char* arg)
{
    return arg && get_fmt_enabled(level, set);                              /* 参数有效且选项启用 */
}

/* ---------------------------------------------- 输出锁管理函数 ---------------------------------------------- */
/**
 * @brief  启用或禁用日志输出锁
 * @param  enabled true:启用  false:禁用
 * @note   不建议禁用此锁，除非需要输出系统异常日志
 *         此函数会根据之前的锁定状态重新锁定或解锁
 */
void elog_output_lock_enabled(bool enabled)
{
    elog.output_lock_enabled = enabled;                                     /* 设置锁启用状态 */
    
    /* 在输出锁启用前重新锁定或解锁 */
    if (elog.output_lock_enabled)
    {
        if (!elog.output_is_locked_before_disable && elog.output_is_locked_before_enable)
        {
            /* 禁用前未锁定，启用后需要锁定 */
            elog_port_output_lock();
        }
        else if (elog.output_is_locked_before_disable && !elog.output_is_locked_before_enable)
        {
            /* 禁用前已锁定，启用后需要解锁 */
            elog_port_output_unlock();
        }
    }
}

/* ---------------------------------------------- 断言钩子函数 ---------------------------------------------- */
/**
 * @brief  设置EasyLogger断言钩子函数
 * @param  hook 钩子函数指针
 * @note   当断言表达式为假时会调用此钩子函数
 *         钩子函数参数：expr-表达式字符串，func-函数名，line-行号
 */
void elog_assert_set_hook(void (*hook)(const char* expr, const char* func, size_t line))
{
    elog_assert_hook = hook;                                                /* 设置断言钩子函数 */
}

/* ---------------------------------------------- 日志解析函数 ---------------------------------------------- */
/**
 * @brief  查找日志级别
 * @param  log 日志缓冲区
 * @return 日志级别，查找失败返回-1
 * @note   确保每种格式都输出日志级别
 *         支持颜色模式和非颜色模式的级别识别
 */
int8_t elog_find_lvl(const char *log)
{
    ELOG_ASSERT(log);                                                       /* 断言日志缓冲区非空 */
    
    /* 确保每种格式都输出日志级别 */
    ELOG_ASSERT(elog.enabled_fmt_set[ELOG_LVL_ASSERT] & ELOG_FMT_LVL);
    ELOG_ASSERT(elog.enabled_fmt_set[ELOG_LVL_ERROR] & ELOG_FMT_LVL);
    ELOG_ASSERT(elog.enabled_fmt_set[ELOG_LVL_WARN] & ELOG_FMT_LVL);
    ELOG_ASSERT(elog.enabled_fmt_set[ELOG_LVL_INFO] & ELOG_FMT_LVL);
    ELOG_ASSERT(elog.enabled_fmt_set[ELOG_LVL_DEBUG] & ELOG_FMT_LVL);
    ELOG_ASSERT(elog.enabled_fmt_set[ELOG_LVL_VERBOSE] & ELOG_FMT_LVL);

#ifdef ELOG_COLOR_ENABLE
    uint8_t i;
    size_t csi_start_len = strlen(CSI_START);                               /* 获取CSI起始标志长度 */
    
    /* 遍历所有级别的颜色信息 */
    for(i = 0; i < ELOG_LVL_TOTAL_NUM; i++)
    {
        /* 比较颜色信息字符串 */
        if (!strncmp(color_output_info[i], log + csi_start_len, strlen(color_output_info[i])))
        {
            return i;                                                       /* 找到匹配的级别 */
        }
    }
    return -1;                                                              /* 查找失败 */
#else
    /* 根据首字符识别级别 */
    switch (log[0])
    {
    case 'A': return ELOG_LVL_ASSERT;                                       /* 断言级别 */
    case 'E': return ELOG_LVL_ERROR;                                        /* 错误级别 */
    case 'W': return ELOG_LVL_WARN;                                         /* 警告级别 */
    case 'I': return ELOG_LVL_INFO;                                         /* 信息级别 */
    case 'D': return ELOG_LVL_DEBUG;                                        /* 调试级别 */
    case 'V': return ELOG_LVL_VERBOSE;                                      /* 详细级别 */
    default: return -1;                                                     /* 未知级别 */
    }
#endif
}

/**
 * @brief  查找日志标签
 * @param  log 日志缓冲区
 * @param  lvl 日志级别，可通过elog_find_lvl()获取
 * @param  tag_len 找到的标签长度
 * @return 日志标签指针，查找失败返回NULL
 * @note   确保每种格式都输出日志标签
 *         标签中不能包含空格字符
 */
const char *elog_find_tag(const char *log, uint8_t lvl, size_t *tag_len)
{
    const char *tag = NULL, *tag_end = NULL;

    ELOG_ASSERT(log);                                                       /* 断言日志缓冲区非空 */
    ELOG_ASSERT(tag_len);                                                   /* 断言标签长度指针非空 */
    ELOG_ASSERT(lvl < ELOG_LVL_TOTAL_NUM);                                  /* 断言级别有效 */
    
    /* 确保每种格式都输出日志标签 */
    ELOG_ASSERT(elog.enabled_fmt_set[lvl] & ELOG_FMT_TAG);

#ifdef ELOG_COLOR_ENABLE
    /* 颜色模式下跳过CSI起始标志、颜色信息和级别信息 */
    tag = log + strlen(CSI_START) + strlen(color_output_info[lvl]) + strlen(level_output_info[lvl]);
#else
    /* 非颜色模式下跳过级别信息 */
    tag = log + strlen(level_output_info[lvl]);
#endif
    
    /* 查找标签后的第一个空格 */
    if ((tag_end = memchr(tag, ' ', ELOG_FILTER_TAG_MAX_LEN)) != NULL)
    {
        *tag_len = tag_end - tag;                                           /* 计算标签长度 */
    }
    else
    {
        tag = NULL;                                                         /* 未找到标签结束位置 */
    }

    return tag;                                                             /* 返回标签指针 */
}

/* ---------------------------------------------- 十六进制转储函数 ---------------------------------------------- */
/**
 * @brief  以十六进制格式转储数据到日志
 * @param  name 十六进制对象名称，将显示在日志头部
 * @param  width 每行显示的十六进制数字个数，如：16、32
 * @param  buf 十六进制缓冲区
 * @param  size 缓冲区大小
 * @note   使用DEBUG级别输出，支持级别和标签过滤
 *         输出格式：地址范围 + 十六进制数据 + ASCII字符
 */
void elog_hexdump(const char *name, uint8_t width, const void *buf, uint16_t size)
{
#define __is_print(ch)       ((unsigned int)((ch) - ' ') < 127u - ' ')      /* 判断字符是否可打印 */

    uint16_t i, j;
    uint16_t log_len = 0;
    const uint8_t *buf_p = buf;                                             /* 缓冲区指针 */
    char dump_string[8] = {0};                                              /* 转储字符串缓冲区 */
    int fmt_result;

    /* 检查输出是否启用 */
    if (!elog.output_enabled)
    {
        return;
    }

    /* 级别过滤 */
    if (ELOG_LVL_DEBUG > elog.filter.level)
    {
        return;
    }
    else if (!strstr(name, elog.filter.tag))                                /* 标签过滤 */
    {
        return;
    }

    /* 锁定输出 */
    elog_output_lock();

    /* 按行处理数据 */
    for (i = 0; i < size; i += width)
    {
        /* 封装头部信息 */
        fmt_result = snprintf(log_buf, ELOG_LINE_BUF_SIZE, "D/HEX %s: %04X-%04X: ", 
                             name, i, i + width - 1);
        
        /* 计算日志长度 */
        if ((fmt_result > -1) && (fmt_result <= ELOG_LINE_BUF_SIZE))
        {
            log_len = fmt_result;                                           /* 使用实际长度 */
        }
        else
        {
            log_len = ELOG_LINE_BUF_SIZE;                                   /* 使用最大长度 */
        }
        
        /* 转储十六进制数据 */
        for (j = 0; j < width; j++)
        {
            if (i + j < size)
            {
                snprintf(dump_string, sizeof(dump_string), "%02X ", buf_p[i + j]);  /* 格式化十六进制 */
            }
            else
            {
                strncpy(dump_string, "   ", sizeof(dump_string));           /* 填充空格 */
            }
            log_len += elog_strcpy(log_len, log_buf + log_len, dump_string);/* 添加到日志缓冲区 */
            
            /* 每8个字节添加额外空格 */
            if ((j + 1) % 8 == 0)
            {
                log_len += elog_strcpy(log_len, log_buf + log_len, " ");
            }
        }
        log_len += elog_strcpy(log_len, log_buf + log_len, "  ");           /* 添加分隔空格 */
        
        /* 转储对应的ASCII字符 */
        for (j = 0; j < width; j++)
        {
            if (i + j < size)
            {
                /* 可打印字符直接显示，否则显示点号 */
                snprintf(dump_string, sizeof(dump_string), "%c", 
                        __is_print(buf_p[i + j]) ? buf_p[i + j] : '.');
                log_len += elog_strcpy(log_len, log_buf + log_len, dump_string);
            }
        }
        
        /* 溢出检查并为换行符预留空间 */
        if (log_len + strlen(ELOG_NEWLINE_SIGN) > ELOG_LINE_BUF_SIZE)
        {
            log_len = ELOG_LINE_BUF_SIZE - strlen(ELOG_NEWLINE_SIGN);
        }
        
        /* 封装换行符 */
        log_len += elog_strcpy(log_len, log_buf + log_len, ELOG_NEWLINE_SIGN);
        
        /* 执行日志输出 */
#if defined(ELOG_ASYNC_OUTPUT_ENABLE)
        extern void elog_async_output(uint8_t level, const char *log, size_t size);
        elog_async_output(ELOG_LVL_DEBUG, log_buf, log_len);                /* 异步输出 */
#elif defined(ELOG_BUF_OUTPUT_ENABLE)
        extern void elog_buf_output(const char *log, size_t size);
        elog_buf_output(log_buf, log_len);                                  /* 缓冲输出 */
#else
        elog_port_output(log_buf, log_len);                                 /* 直接输出 */
#endif
    }
    
    /* 解锁输出 */
    elog_output_unlock();
}
